package com.travel.modules.alipay.controller;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import com.travel.commons.utils.R;
import com.travel.config.AliPayConfig;
import com.travel.modules.alipay.dto.AlipayDTO;
import com.travel.modules.alipay.entity.OrderForm;
import com.travel.modules.alipay.service.OrderFormService;
import com.travel.modules.alipay.worker.OrderStatusChecker;
import com.travel.modules.asset.service.GoodsService;
import com.travel.modules.sys.entity.SysConfig;
import com.travel.modules.sys.service.SysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

@Slf4j
@RestController
@RequestMapping("/alipay")
public class AlipayController {
    @Resource
    private AliPayConfig aliPayConfig;

    @Resource
    private OrderFormService orderFormService;

    @Resource
    private SysConfigService sysConfigService;

    @Resource
    private GoodsService goodsService;

    private static final String SYSTEM_CONFIG_TEST_ORDER_NO = "SYSTEM_CONFIG_TEST_ORDER_NO";

    private static final String PRODUCT_CODE = "FAST_INSTANT_TRADE_PAY";

    /**
     * 商品支付页面
     * @param form  private String subject          商品名称
     *              private String out_trade_no     唯一订单号
     *              private String total_amount     支付金额
     *              private String product_code     销售产品码，与支付宝签约的产品码名称，沙箱环境固定为 FAST_INSTANT_TRADE_PAY
     *              {@link com.travel.modules.alipay.dto.AlipayDTO}
     * @return 支付页面
     */
    @RequestMapping("/in")
    public R alipayTest(@RequestBody AlipayDTO form) throws AlipayApiException {
        form.setProduct_code(PRODUCT_CODE);
        String json = new Gson().toJson(form);

        AlipayClient alipayClient = new DefaultAlipayClient(
                aliPayConfig.getGatewayHost(),
                aliPayConfig.getAppId(),
                aliPayConfig.getPrivateKey(),
                "json", "UTF-8",
                aliPayConfig.getPublicKey(),
                aliPayConfig.getSignType());

        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(aliPayConfig.getReturnUrl());
        alipayRequest.setNotifyUrl(aliPayConfig.getNotifyUrl());
        alipayRequest.setBizContent(json);
        String result = alipayClient.pageExecute(alipayRequest).getBody();
        return R.ok().put("page", result);
    }

    /**
     * 商家端回调
     */
    @RequestMapping("/notify")
    public R alipayNotify(@RequestParam Map<String, String> params) {
        log.info("params : " + params);
        String orderId = params.get("out_trade_no");
        BigDecimal pay = new BigDecimal(params.get("buyer_pay_amount"));
        OrderForm form = orderFormService.getOne(new QueryWrapper<OrderForm>().eq("order_id", orderId));
        if (form == null) {
            return R.error("订单不存在");
        }
        form.setRealPay(pay);
        form.setStatus(1);
        form.setExpireTime(null);

        Object goodsObj = goodsService.getGoodsObject(form.getGoodsId());
        if (goodsObj == null) {
            return R.error("商品不存在");
        }
        goodsService.addHot(goodsObj, form.getGoodsId());
        orderFormService.updateById(form);
        return R.ok();
    }

    /**
     * 买家页面跳转时回调
     */
    @RequestMapping("/return")
    public R alipayReturn(@RequestBody Map<String, String> params) {
        String orderId = params.get("orderId");

        FutureTask<R> result = new FutureTask<>(new OrderStatusChecker(orderId, orderFormService, goodsService));
        new Thread(result).start();
        R r;
        try {
            r = result.get();
        } catch (InterruptedException | ExecutionException e) {
            log.error(e.getMessage());
            r = R.error(e.getMessage());
        }
        return r;
    }

    @RequestMapping("/order/no")
    public R getOrderNo() {
        String orderNo = sysConfigService.getValue(SYSTEM_CONFIG_TEST_ORDER_NO);
        SysConfig sysConfig = sysConfigService.getOne(new QueryWrapper<SysConfig>().eq("config_key", SYSTEM_CONFIG_TEST_ORDER_NO));
        sysConfig.setConfigValue(Integer.parseInt(sysConfig.getConfigValue()) + 1 + "");
        sysConfigService.updateById(sysConfig);
        return R.ok().put("page", orderNo);
    }
}
